package cn.xenosp.server.common.sse;

import cn.hutool.core.util.StrUtil;
import cn.xenosp.server.common.MessageTypeEeum;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;

/**
 * 项目名： service-web
 * 包路径： cn.xenosp.server.common.tools
 * 作者：   TongHui
 * 创建时间: 2024-09-04 11:22
 * 描述: SSE 消息推送
 * 版本: 1.0
 */

@Slf4j
public class SseClient {
    private static final Logger logger = LoggerFactory.getLogger(SseClient.class);
    /**
     * 发送心跳线程池
     */
    private static ScheduledExecutorService heartbeatExecutors = Executors.newScheduledThreadPool(8);

    /**
     * 创建连接
     */
    public static SseEmitter createSse(SseVO sseVO) {
        //默认30秒超时,设置为0L则永不超时
        SseEmitter sseEmitter = new SseEmitter(0l);
        logger.info("SSE 创建连接 | ID: {} | Date: {}",  sseVO.getUid(), new Date());
        if (!SseSession.add(sseVO.getUid(), sseEmitter)) {
            return SseSession.get(sseVO.getUid());
        }
        final ScheduledFuture<?> future = heartbeatExecutors.scheduleAtFixedRate(new HeartBeatTask(sseVO), 0, sseVO.getTimeout(), TimeUnit.SECONDS);
        sseEmitter.onCompletion(() -> {
            logger.info("SSE 关闭连接 |ID: {} | Date: {}",  sseVO.getUid(), new Date());
            future.cancel(true);
            SseSession.onCompletion(sseVO.getUid());
        });
        sseEmitter.onTimeout(() -> {
            logger.error("SSE 连接超时 |ID: {} | Date: {}", sseVO.getUid(), new Date());
            future.cancel(true);
            SseSession.onError(sseVO.getUid(), new RuntimeException("TimeOut(clientId: " + sseVO.getUid() + ")"));
        });
        sseEmitter.onError(t -> {
            logger.error("SSE 连接错误 |ID: {} | Date: {}",  sseVO.getUid(), new Date());
            future.cancel(true);
            SseSession.onError(sseVO.getUid(), new RuntimeException("Error(clientId: " + sseVO.getUid() + ")"));
        });
        return sseEmitter;
    }

    /**
     * 给指定用户发送消息
     *
     */
    public static boolean sendMessage(String uid,String messageId, String message) {
        if (StrUtil.isBlank(message)) {
            log.info("{}参数异常，msg为null", uid);
            return false;
        }
        return SseSession.send(uid,SseEmitter.event().id(messageId).reconnectTime(5000).data(message));
    }

    /**
     * 断开
     * @param uid
     */
    public static void close(String uid){
        log.info("用户{} 关闭连接",uid);
        SseSession.del(uid);
    }

    public static Set<String> getAllSession(){
        return SseSession.getAllSession();
    }
}
